import socket
import pickle
import json
import logging
import numpy as np
from typing import Dict, Any, List
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.asymmetric import rsa
import base64
from datetime import datetime
from config import FERNET_KEY, LOG_LEVEL, LOG_FORMAT, LOG_DIR
from pathlib import Path
import os
import sys 
# 将项目根目录添加到 sys.path
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.append(project_root)
from src2.config import FORMAT_RULES

import os

class CentralServer:
    def __init__(self, host='localhost', port=5000):
        self.host = host
        self.port = port
        self.logger = self.setup_logger()
        # 初始化 participant_data 为一个空列表
        self.participant_data = []
        # 初始化 cipher_suite
        self.cipher_suite = Fernet(FERNET_KEY)
        # 生成私钥用于签名
        self.private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048,
        )

    def setup_logger(self):
        # 确保日志目录存在
        os.makedirs(LOG_DIR, exist_ok=True)
        # 创建日志记录器
        logger = logging.getLogger('CentralServer')
        logger.setLevel(LOG_LEVEL)
        # 创建文件处理器
        file_handler = logging.FileHandler(os.path.join(LOG_DIR, 'server.log'))
        file_handler.setLevel(LOG_LEVEL)
        # 创建控制台处理器
        console_handler = logging.StreamHandler()
        console_handler.setLevel(LOG_LEVEL)
        # 创建格式化器并添加到处理器
        formatter = logging.Formatter(LOG_FORMAT)
        file_handler.setFormatter(formatter)
        console_handler.setFormatter(formatter)
        # 将处理器添加到日志记录器
        logger.addHandler(file_handler)
        logger.addHandler(console_handler)
        return logger

    def start_server(self):
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                s.bind((self.host, self.port))
                s.listen()
                self.logger.info(f"服务器启动在 {self.host}:{self.port}")
                while True:
                    conn, addr = s.accept()
                    with conn:
                        self.logger.info(f"连接来自 {addr}")
                        data = conn.recv(4096)
                        if data:
                            self.process_participant_data(pickle.loads(data))
        except Exception as e:
            self.logger.error(f"服务器运行出错: {str(e)}")

    def process_participant_data(self, data):
        """处理参与者数据"""
        try:
            self.participant_data.append(data)
            self.logger.info(f"成功处理来自参与者的数据")
        except Exception as e:
            self.logger.error(f"处理参与者数据时出错: {str(e)}")

    def verify_metadata_consistency(self) -> bool:
        """验证元数据一致性"""
        if not self.participant_data:
            self.logger.warning("没有参与者数据")
            return False

        try:
            # 获取第一个参与者的元数据哈希作为基准
            base_hash = self.participant_data[0]['metadata_hash']

            # 验证其他参与者的元数据哈希是否一致
            for data in self.participant_data[1:]:
                if data['metadata_hash'] != base_hash:
                    self.logger.warning("元数据不一致")
                    return False
            return True
        except Exception as e:
            self.logger.error(f"验证元数据一致性时出错: {str(e)}")
            return False

    def aggregate_compliance_results(self) -> Dict[str, float]:
    
     if not self.participant_data:
        self.logger.warning("没有参与者数据")
        return {}

     try:
        aggregated_results = {}
        total_participants = len(self.participant_data)
        self.logger.info(f"开始聚合 {total_participants} 个参与者的合规性结果")

        for i, data in enumerate(self.participant_data):
            try:
                if 'encrypted_data' not in data:
                    self.logger.error(f"参与者 {i + 1} 的数据缺少 encrypted_data 字段")
                    continue

                decrypted_data = self.cipher_suite.decrypt(data['encrypted_data'])
                participant_data = json.loads(decrypted_data)
                self.logger.info(f"成功解密参与者 {i + 1} 的数据")

                if not isinstance(participant_data, dict):
                    self.logger.error(f"参与者 {i + 1} 的数据格式错误")
                    continue

                for col, value in participant_data.items():
                    if col in FORMAT_RULES and FORMAT_RULES[col] == 'numeric':
                        try:
                            if isinstance(value, dict):
                                # 处理字典形式的数据
                                numeric_values = [float(v) for v in value.values() if isinstance(v, (int, float)) or (isinstance(v, str) and v.replace('.', '', 1).isdigit())]
                                if numeric_values:
                                    avg_value = sum(numeric_values) / len(numeric_values)
                                else:
                                    self.logger.warning(f"参与者 {i + 1} 的字段 {col} 没有有效的数值数据")
                                    continue
                            elif isinstance(value, list):
                                # 如果是列表，尝试计算平均值
                                numeric_values = [float(v) for v in value if isinstance(v, (int, float)) or (isinstance(v, str) and v.replace('.', '', 1).isdigit())]
                                if numeric_values:
                                    avg_value = sum(numeric_values) / len(numeric_values)
                                else:
                                    self.logger.warning(f"参与者 {i + 1} 的字段 {col} 没有有效的数值数据")
                                    continue
                            elif isinstance(value, (int, float)):
                                avg_value = float(value)
                            elif isinstance(value, str) and value.replace('.', '', 1).isdigit():
                                avg_value = float(value)
                            else:
                                self.logger.warning(f"参与者 {i + 1} 的字段 {col} 的值 '{value}' 无法转换为数值类型")
                                continue

                            if col not in aggregated_results:
                                aggregated_results[col] = 0.0
                            aggregated_results[col] += avg_value
                        except ValueError:
                            self.logger.warning(f"参与者 {i + 1} 的字段 {col} 的值 '{value}' 无法转换为数值类型")
                    else:
                        self.logger.warning(f"参与者 {i + 1} 的字段 {col} 不是数值类型，无法聚合")

            except json.JSONDecodeError as e:
                self.logger.error(f"参与者 {i + 1} 的数据JSON解析错误: {str(e)}")
                continue
            except Exception as e:
                self.logger.error(f"处理参与者 {i + 1} 的数据时出错: {str(e)}")
                continue

        if aggregated_results:
            for col in aggregated_results:
                aggregated_results[col] /= total_participants
            self.logger.info("成功计算所有字段的平均值")
        else:
            self.logger.warning("没有有效的数据可以聚合")

        return aggregated_results

     except Exception as e:
        self.logger.error(f"聚合数据时发生未预期的错误: {str(e)}")
        return {}

    def generate_global_report(self) -> Dict[str, Any]:
        """生成全局报告"""
        try:
            metadata_consistent = self.verify_metadata_consistency()
            aggregated_results = self.aggregate_compliance_results()

            # 计算总体质量分数
            overall_score = 0.0
            if aggregated_results:
                scores = list(aggregated_results.values())
                if scores:
                    overall_score = float(np.mean(scores))

            report = {
                "metadata_consistency": metadata_consistent,
                "aggregated_results": aggregated_results,
                "total_participants": len(self.participant_data),
                "overall_quality_score": overall_score,
                "generated_at": datetime.now().isoformat()
            }

            return report
        except Exception as e:
            self.logger.error(f"生成全局报告时出错: {str(e)}")
            return {
                "error": str(e),
                "metadata_consistency": False,
                "aggregated_results": {},
                "total_participants": 0,
                "overall_quality_score": 0.0,
                "generated_at": datetime.now().isoformat()
            }

    def sign_report(self, report: Dict[str, Any]) -> str:
        """对报告进行数字签名"""
        try:
            report_str = json.dumps(report, sort_keys=True)
            signature = self.private_key.sign(
                report_str.encode(),
                padding.PSS(
                    mgf=padding.MGF1(hashes.SHA256()),
                    salt_length=padding.PSS.MAX_LENGTH
                ),
                hashes.SHA256()
            )
            return base64.b64encode(signature).decode('utf-8')
        except Exception as e:
            self.logger.error(f"签名报告时出错: {str(e)}")
            return ""

    def encrypt_and_store_report(self, report: Dict[str, Any], signature: str, output_path: str):
        """加密并存储报告"""
        try:
            report_data = {
                "report": report,
                "signature": signature
            }

            encrypted_data = self.cipher_suite.encrypt(
                json.dumps(report_data).encode()
            )

            with open(output_path, 'wb') as f:
                f.write(encrypted_data)
            self.logger.info(f"报告已成功存储到 {output_path}")
        except Exception as e:
            self.logger.error(f"存储报告时出错: {str(e)}")

    def generate_plain_report(self, report: Dict[str, Any], signature: str, output_path: str):
        """生成不加密的报告"""
        try:
            report_data = {
                "report": report,
                "signature": signature,
                "generated_at": datetime.now().isoformat(),
                "report_version": "1.0"
            }

            # 格式化JSON输出
            formatted_json = json.dumps(report_data,
                                     indent=4,
                                     ensure_ascii=False,
                                     sort_keys=True)

            with open(output_path, 'w', encoding='utf-8') as f:
                f.write(formatted_json)
            self.logger.info(f"不加密报告已成功存储到 {output_path}")

            # 打印报告摘要
            self.print_report_summary(report)
        except Exception as e:
            self.logger.error(f"生成不加密报告时出错: {str(e)}")

    def print_report_summary(self, report: Dict[str, Any]):
        """打印报告摘要"""
        print("\n=== 数据质量检查报告摘要 ===")
        print(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"参与方数量: {report['total_participants']}")
        print(f"元数据一致性: {'通过' if report['metadata_consistency'] else '未通过'}")
        print("\n聚合结果:")
        for col, score in report['aggregated_results'].items():
            print(f"- {col}: {score:.2f}")
        print(f"\n总体质量分数: {report['overall_quality_score']:.2f}")
        print("=" * 30)

    def generate_final_report(self):
        report = self.generate_global_report()
        signature = self.sign_report(report)

        # 存储加密报告
        self.encrypt_and_store_report(
            report,
            signature,
            os.path.join('reports', 'report.enc')
        )

        # 存储不加密报告
        self.generate_plain_report(
            report,
            signature,
            os.path.join('reports', 'report.json')
        )


def main():
    server = CentralServer()
    try:
        server.start_server()
    except KeyboardInterrupt:
        print("\n服务器已停止")
    except Exception as e:
        server.logger.error(f"服务器运行出错: {str(e)}")
        raise


if __name__ == "__main__":
    main()